package gui;

import database.entity.Contact;
import database.entity.Mail;
import gui.component.image.ResourceLoader;
import java.awt.event.ActionEvent;
import java.security.InvalidKeyException;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.swing.ImageIcon;
import javax.swing.JMenuItem;
import org.apache.commons.codec.binary.Base64;
import security.AESKey;
import security.Hash;
import security.RSAKeyPair;

/**
 *
 * @author Tom
 */
public class UIViewMail extends javax.swing.JDialog {

    static ImageIcon imgTick = new ImageIcon(ResourceLoader.class.getResource("tick.png"));
    static ImageIcon imgPass = new ImageIcon(ResourceLoader.class.getResource("passed.png"));
    static ImageIcon imgFail = new ImageIcon(ResourceLoader.class.getResource("cross.png"));
    
    UIMain parent;
    Mail mail;
    boolean isSentMail;
    
    //UIViewMail _this;
    
    public UIViewMail(UIMain parent, Mail mail)
    {                
        super(parent,true);        
        this.parent=parent;
        initComponents();
        this.mail=mail;
        displayMail();
        pack();
        setLocationRelativeTo(null);
    }

    private void displayMail()
    {
        Base64 decoder = new Base64();
        //display subject
        lbSubject.setText(mail.Subject);
        
        //show CC, separate CCs
        if (!"".equals(mail.CC) && mail.CC!=null)
        {                                  
            String[] CCs = mail.CC.split(",");
            String text="";
            for (String CC : CCs)
            {
                text+=parent.user.databaseWorker.getContactNameFromEmail(CC, true) +"; ";
            }
            lbCC2.setText(text);
        }
        else
        {
            lbCC1.setVisible(false);
            lbCC2.setVisible(false);
        }

        //show BCC, separate BCCs
        if (!"".equals(mail.BCC) && mail.BCC!=null)
        {
            String[] BCCs = mail.BCC.split(",");
            String text="";
            for (String BCC : BCCs)
            {
                text+=parent.user.databaseWorker.getContactNameFromEmail(BCC, true) +"; ";
            }
            lbBCC2.setText(text);
        }
        else
        {
            lbBCC1.setVisible(false);
            lbBCC2.setVisible(false);
        }
        
        //check if this mail is sent or received        
        if (parent.user.Email.equals(mail.From))
        {
            //is sent
            isSentMail=true;
            //show receivers, separate receivers
            lbSenderReceiver.setText("To");
            
            String[] TOs = mail.To.split(",");
            String text="";
            for (String TO : TOs)
            {
                text+=parent.user.databaseWorker.getContactNameFromEmail(TO, true) +"; ";
            }            
            lbSenderReceiver2.setText(text);                        
                                    
            lbTime.setText(mail.SentDate.toString());
            
            //show content
            if (mail.Signed)
            {
                lbImgSign.setIcon(imgTick);
                lbSignInfo.setText("Vous avez signé ce message");
            }
            else
            {
                lbImgSign.setIcon(imgPass);
                lbSignInfo.setText("Vous n'avez pas signé ce message");
            }
            if (mail.Encrypted)
            {                
                lbImgEncrypt.setIcon(imgTick);
                lbEncryptInfo.setText("Vous avez chiffré ce message");                                
                //show content
                //retrieve message content
                //get k_aes by decode E(k_pub_send, k_aes) in header3
                AESKey aesKey = new AESKey(parent.user.keypair.decodeByPrivateKey(decoder.decode(mail.HeaderField3)));
                
                String clairMessage;
                try 
                {
                    //decode the message                    
                    clairMessage= new String(aesKey.decode(mail.Content.getBytes()));
                    txtMessage.setText(clairMessage);
                }
                catch (IllegalBlockSizeException | InvalidKeyException | BadPaddingException | NoSuchPaddingException ex) 
                {
                    txtMessage.setText("<Le contenu du message a été endommagé>");
                }
            }
            else
            {                
                lbImgEncrypt.setIcon(imgPass);
                lbEncryptInfo.setText("Vous n'avez pas chiffré ce message");                                
                //show content                 
                txtMessage.setText(mail.Content);
            }
        }
        else
        {
            //is received
            isSentMail=false;
            
            //show sender
            lbSenderReceiver.setText("De");
            lbSenderReceiver2.setText(parent.user.databaseWorker.getContactNameFromEmail(mail.From,true));
            lbTime.setText(mail.ReceivedDate.toString());
            //show content
            if (!mail.Signed)
            {
                //means neither encrypted
                lbImgSign.setIcon(imgPass);
                lbSignInfo.setText("Ce message n'a pas été signé");
                lbImgEncrypt.setIcon(imgPass);
                lbEncryptInfo.setText("Ce message n'a pas été chiffré");
                txtMessage.setText(mail.Content);
            }
            else
            {               
                //check if user is existed in contact list
                Contact ct = parent.user.databaseWorker.getContactFromEmail(mail.From);
                if (ct==null || ct.PublicKey==null)
                {
                    //contact not found
                    lbImgSign.setIcon(imgPass);
                    if (ct==null)
                    {                        
                        lbSignInfo.setText("Vous n'avez pas aucune d'information de cet expéditeur");                    
                    }
                    else
                    {                        
                        lbSignInfo.setText("Vous n'avez pas la clé publique du contact pour vérifier son identité");
                    }
                }
                else
                {
                    //contact and key found
                    RSAKeyPair rsaSender = new RSAKeyPair(decoder.decode(ct.PublicKey), true);
                    if (!mail.Encrypted)
                    {
                        //not encrypted
                        lbImgEncrypt.setIcon(imgPass);
                        lbEncryptInfo.setText("Ce message n'a pas été chiffré");
 
                        //set content
                        txtMessage.setText(mail.Content);
                        
                        //verify signature                                                 
                        String hashed = Hash.generateSHA256(mail.Content);
                        
                        //take hashed from header1
                        //String tmp = 
                        String hashedHeader = new String(rsaSender.decodeByPublicKey(decoder.decode(mail.HeaderField1)));
                        if (hashed.equals(hashedHeader))
                        {
                            lbImgSign.setIcon(imgTick);
                            lbSignInfo.setText("Signature verifiée");
                        }
                        else
                        {
                            lbImgSign.setIcon(imgFail);
                            lbSignInfo.setText("Vérification de signature échouée");
                        }
                    }
                    else
                    {
                        boolean decryptSucceeded=false;
                        try 
                        {
                            //encrypted

                            //reconstruct AESKey to decrypt message
                            AESKey aes = new AESKey(parent.user.keypair.decodeByPrivateKey(decoder.decode(mail.HeaderField2)));
                            String clearMessage = new String(aes.decode(decoder.decode(mail.Content)));
                            
                            //verify signature
                            String hashed = Hash.generateSHA256(clearMessage);
                            //take hashed from header1
                            String hashedHeader = new String(rsaSender.decodeByPublicKey(decoder.decode(mail.HeaderField1)));
                            if (hashed.equals(hashedHeader))
                            {
                                decryptSucceeded=true;
                            }
                            txtMessage.setText(clearMessage);
                        } 
                        catch (IllegalBlockSizeException | InvalidKeyException | BadPaddingException | NoSuchPaddingException ex) 
                        {
                            //ex.printStackTrace();
                            decryptSucceeded=false;
                        }
                        if (decryptSucceeded)
                        {

                            lbImgSign.setIcon(imgTick);
                            lbSignInfo.setText("Signature verifiée");
                            lbImgEncrypt.setIcon(imgTick);
                            lbEncryptInfo.setText("Ce message a été bien chiffré");
                        }
                        else
                        {
                            lbImgSign.setIcon(imgFail);
                            lbSignInfo.setText("Vérification de signature échouée");
                            lbImgEncrypt.setIcon(imgFail);
                            lbImgEncrypt.setText("Message est endomagé");
                            txtMessage.setText("<Le contenu du message a été endommagé>");
                        }
                    }   
                }
            }
        }                
    }
    
    private void populateMenu()
    {
        menuAction.removeAll();
        if (isSentMail)
        {
            JMenuItem mnu1 = new JMenuItem("Réenvoyer");
            mnu1.addActionListener((ActionEvent ae) -> 
            {
                parent.user.databaseWorker.sendMail(mail.Subject, mail.Content, mail.To, mail.CC,
                        mail.BCC, mail.Signed, mail.Encrypted);
                dispose();
            });  
            JMenuItem mnu2 = new JMenuItem("Editer");
            mnu2.addActionListener((ActionEvent ae) -> 
            {
                setVisible(false);
                UINewMail newMail = new UINewMail(parent,mail.Subject,mail.Content,mail.To, mail.CC,mail.BCC);
                newMail.setVisible(true);
                dispose();
            });
            JMenuItem mnu3 = new JMenuItem("Supprimer");
            mnu3.addActionListener((ActionEvent ae) -> 
            {
                //remove mail rom database
                parent.user.databaseWorker.deleteMail(mail.MailID);
                //update parent UI
                parent.loadMailToList(parent.currentMailBox);
                dispose();
            });
            menuAction.add(mnu1);
            menuAction.add(mnu2);
            menuAction.add(mnu3);
        }
        else
        {
            JMenuItem mnu1 = new JMenuItem("Répondre");
            mnu1.addActionListener((ActionEvent ae) -> 
            {
                setVisible(false);
                UINewMail newMail = new UINewMail(parent,"Re: "+mail.Subject,"",mail.To,null,null);
                newMail.setVisible(true);
                dispose();
            });  
            JMenuItem mnu2 = new JMenuItem("Répondre à tous");
            mnu2.addActionListener((ActionEvent ae) -> 
            {
                setVisible(false);
                UINewMail newMail = new UINewMail(parent,"Re: "+mail.Subject,"", mail.To,mail.CC,mail.BCC);
                newMail.setVisible(true);
                dispose();
            });
            JMenuItem mnu3 = new JMenuItem("Transférer");
            mnu3.addActionListener((ActionEvent ae) -> 
            {
                setVisible(false);
                UINewMail newMail = new UINewMail(parent,"Forward: "+mail.Subject,mail.Content,null,null,null);
                newMail.setVisible(true);
                dispose();
            });
            JMenuItem mnu4 = new JMenuItem("Supprimer");
            mnu4.addActionListener((ActionEvent ae) -> 
            {
                //remove mail rom database
                parent.user.databaseWorker.deleteMail(mail.MailID);
                //update parent UI
                parent.loadMailToList(parent.currentMailBox);
                dispose();
            });
            menuAction.add(mnu1);
            menuAction.add(mnu2);
            menuAction.add(mnu3);
            menuAction.add(mnu4);
        }
    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        menuAction = new javax.swing.JPopupMenu();
        jLabel1 = new javax.swing.JLabel();
        lbSubject = new javax.swing.JLabel();
        jScrollPane1 = new javax.swing.JScrollPane();
        txtMessage = new javax.swing.JTextArea();
        lbSenderReceiver = new javax.swing.JLabel();
        btAction = new javax.swing.JButton();
        lbSenderReceiver2 = new javax.swing.JLabel();
        lbImgSign = new javax.swing.JLabel();
        lbImgEncrypt = new javax.swing.JLabel();
        lbSignInfo = new javax.swing.JLabel();
        lbEncryptInfo = new javax.swing.JLabel();
        lbTime = new javax.swing.JLabel();
        lbCC1 = new javax.swing.JLabel();
        lbCC2 = new javax.swing.JLabel();
        lbBCC1 = new javax.swing.JLabel();
        lbBCC2 = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);

        jLabel1.setText("Objet");

        lbSubject.setBackground(new java.awt.Color(255, 255, 255));
        lbSubject.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N
        lbSubject.setOpaque(true);

        txtMessage.setEditable(false);
        txtMessage.setColumns(20);
        txtMessage.setFont(new java.awt.Font("Monospaced", 0, 16)); // NOI18N
        txtMessage.setRows(5);
        txtMessage.setWrapStyleWord(true);
        jScrollPane1.setViewportView(txtMessage);

        lbSenderReceiver.setText("Sender/Receiver");

        btAction.setText("...");
        btAction.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btActionActionPerformed(evt);
            }
        });

        lbTime.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);

        lbCC1.setText("CC");

        lbBCC1.setText("BCC");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 849, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(lbImgSign, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(lbImgEncrypt, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(lbEncryptInfo, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(lbSignInfo, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                            .addComponent(lbBCC1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(lbCC1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(jLabel1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(lbSenderReceiver, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 95, Short.MAX_VALUE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(lbSubject, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(btAction))
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(lbSenderReceiver2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(lbTime, javax.swing.GroupLayout.PREFERRED_SIZE, 236, javax.swing.GroupLayout.PREFERRED_SIZE))
                            .addComponent(lbCC2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(lbBCC2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(lbSubject, javax.swing.GroupLayout.DEFAULT_SIZE, 30, Short.MAX_VALUE)
                    .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(btAction, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                        .addComponent(lbSenderReceiver2, javax.swing.GroupLayout.PREFERRED_SIZE, 28, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addComponent(lbSenderReceiver, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(lbTime, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(lbCC1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(lbCC2, javax.swing.GroupLayout.PREFERRED_SIZE, 28, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(16, 16, 16)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(lbBCC1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(lbBCC2, javax.swing.GroupLayout.PREFERRED_SIZE, 28, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 287, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(lbImgSign, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(lbSignInfo, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(lbEncryptInfo, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(lbImgEncrypt, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void btActionActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btActionActionPerformed
        populateMenu();
        menuAction.show(btAction, 10, 10);
    }//GEN-LAST:event_btActionActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btAction;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JLabel lbBCC1;
    private javax.swing.JLabel lbBCC2;
    private javax.swing.JLabel lbCC1;
    private javax.swing.JLabel lbCC2;
    private javax.swing.JLabel lbEncryptInfo;
    private javax.swing.JLabel lbImgEncrypt;
    private javax.swing.JLabel lbImgSign;
    private javax.swing.JLabel lbSenderReceiver;
    private javax.swing.JLabel lbSenderReceiver2;
    private javax.swing.JLabel lbSignInfo;
    private javax.swing.JLabel lbSubject;
    private javax.swing.JLabel lbTime;
    private javax.swing.JPopupMenu menuAction;
    private javax.swing.JTextArea txtMessage;
    // End of variables declaration//GEN-END:variables
}
